package com.agent.platform.service;

import com.agent.platform.dto.CreateAgentRequest;
import com.agent.platform.entity.Agent;
import com.agent.platform.repository.AgentRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Agent管理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AgentService {

    private final AgentRepository agentRepository;

    @Value("${agent.platform.default.context-manager-url}")
    private String defaultContextManagerUrl;

    @Value("${agent.platform.default.tool-manager-url}")
    private String defaultToolManagerUrl;

    @Value("${agent.platform.default.model-selector-url}")
    private String defaultModelSelectorUrl;

    /**
     * 创建Agent
     */
    @Transactional
    public Agent createAgent(CreateAgentRequest request) {
        if (agentRepository.existsByAgentId(request.getAgentId())) {
            throw new IllegalArgumentException("Agent already exists: " + request.getAgentId());
        }

        Agent agent = new Agent();
        agent.setAgentId(request.getAgentId());
        agent.setContextManagerUrl(
            request.getContextManagerUrl() != null ? request.getContextManagerUrl() : defaultContextManagerUrl
        );
        agent.setToolManagerUrl(
            request.getToolManagerUrl() != null ? request.getToolManagerUrl() : defaultToolManagerUrl
        );
        agent.setModelSelectorUrl(
            request.getModelSelectorUrl() != null ? request.getModelSelectorUrl() : defaultModelSelectorUrl
        );

        // 设置控制配置（使用默认值）
        Map<String, Object> controlConfig = request.getControlConfig() != null
            ? request.getControlConfig()
            : getDefaultControlConfig();
        agent.setControlConfig(controlConfig);

        agent.setMetadata(request.getMetadata());
        agent.setStatus("active");

        Agent savedAgent = agentRepository.save(agent);
        log.info("Created agent: {}", savedAgent.getAgentId());

        return savedAgent;
    }

    /**
     * 获取Agent
     */
    public Agent getAgent(String agentId) {
        return agentRepository.findByAgentId(agentId)
            .orElseThrow(() -> new IllegalArgumentException("Agent not found: " + agentId));
    }

    /**
     * 更新Agent
     */
    @Transactional
    public Agent updateAgent(String agentId, CreateAgentRequest request) {
        Agent agent = getAgent(agentId);

        if (request.getContextManagerUrl() != null) {
            agent.setContextManagerUrl(request.getContextManagerUrl());
        }
        if (request.getToolManagerUrl() != null) {
            agent.setToolManagerUrl(request.getToolManagerUrl());
        }
        if (request.getModelSelectorUrl() != null) {
            agent.setModelSelectorUrl(request.getModelSelectorUrl());
        }
        if (request.getControlConfig() != null) {
            agent.setControlConfig(request.getControlConfig());
        }
        if (request.getMetadata() != null) {
            agent.setMetadata(request.getMetadata());
        }

        Agent updated = agentRepository.save(agent);
        log.info("Updated agent: {}", agentId);

        return updated;
    }

    /**
     * 删除Agent
     */
    @Transactional
    public void deleteAgent(String agentId, boolean force) {
        Agent agent = getAgent(agentId);

        if (force) {
            agentRepository.delete(agent);
            log.info("Force deleted agent: {}", agentId);
        } else {
            agent.setStatus("deleted");
            agentRepository.save(agent);
            log.info("Soft deleted agent: {}", agentId);
        }
    }

    /**
     * 列出所有Agent
     */
    public List<Agent> listAgents(String status) {
        if (status != null) {
            return agentRepository.findByStatus(status);
        }
        return agentRepository.findAll();
    }

    /**
     * 更新控制配置
     */
    @Transactional
    public Agent updateControlConfig(
        String agentId,
        Map<String, Object> propertyMap,
        String updatedBy,
        String reason,
        boolean effectiveImmediately
    ) {
        Agent agent = getAgent(agentId);

        Map<String, Object> controlConfig = agent.getControlConfig();
        if (controlConfig == null) {
            controlConfig = new HashMap<>();
        }

        // 更新配置属性
        for (Map.Entry<String, Object> entry : propertyMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            // 支持嵌套属性 (如 "rateLimiting.requestsPerMinute")
            if (key.contains(".")) {
                updateNestedProperty(controlConfig, key, value);
            } else {
                controlConfig.put(key, value);
            }
        }

        agent.setControlConfig(controlConfig);
        Agent updated = agentRepository.save(agent);

        log.info("Updated control config for agent: {} by: {} reason: {}",
            agentId, updatedBy, reason);

        return updated;
    }

    /**
     * 默认控制配置
     */
    private Map<String, Object> getDefaultControlConfig() {
        Map<String, Object> config = new HashMap<>();
        config.put("maxSteps", 50);
        config.put("maxFailures", 3);
        config.put("maxExecutionTime", 300000);
        config.put("maxTokensPerRequest", 4000);
        config.put("maxCostPerSession", 10.0);
        config.put("enableToolUsage", true);

        Map<String, Object> rateLimiting = new HashMap<>();
        rateLimiting.put("requestsPerMinute", 60);
        rateLimiting.put("requestsPerHour", 1000);
        config.put("rateLimiting", rateLimiting);

        return config;
    }

    /**
     * 更新嵌套属性
     */
    @SuppressWarnings("unchecked")
    private void updateNestedProperty(Map<String, Object> config, String key, Object value) {
        String[] parts = key.split("\\.");
        Map<String, Object> current = config;

        for (int i = 0; i < parts.length - 1; i++) {
            String part = parts[i];
            if (!current.containsKey(part)) {
                current.put(part, new HashMap<String, Object>());
            }
            current = (Map<String, Object>) current.get(part);
        }

        current.put(parts[parts.length - 1], value);
    }
}
